﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using OpenLab.BLL;
using OpenLab.Model;
using OpenLab.Model.ViewModel;
using OpenLab.UI.Helper;
using OpenLab.UI.Properties;

namespace OpenLab.UI.Reception
{
    public partial class AjoutDemande : Form
    {
        private Client _client = new Client();
        readonly ClientBLL _clientBll = new ClientBLL();
        readonly DemandeBLL _demandeBll = new DemandeBLL();
        readonly DetailDemandeBLL _detailDemandeBll = new DetailDemandeBLL();

        readonly BindingSource _bsListeAnalyse = new BindingSource();
        readonly BindingSource _bsAnalyseDestination = new BindingSource();
        private List<PrixAnalyseOrganisme> _listPrixAnalyseOrganisme;
        private List<DemandeAnalyse> _listDemandeAnalyse = new List<DemandeAnalyse>();

        decimal _mnttotal, _mntpat;

        public AjoutDemande()
        {
            InitializeComponent();
            
            Load += AjoutDemande_Load;

            InitLists();
            
            clientsdgv.CellContentClick += clientsdgv_CellContentClick;

            Activated += AjoutDemande_Activated;
            
            exitbtn.Click+= delegate { Close();};
        }

        void clientsdgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (clientsdgv.CurrentRow == null) return;
            
            var id = (int) clientsdgv.CurrentRow.Cells["id"].Value;
            _client = _clientBll.GetById(id);
            BindClient();
        }

        void GetClient()
        {
            _client.nom            = nomtxt.Text               ;
            _client.prenom         = prenomtxt.Text            ;
            _client.datenaissance  = datenaissancedat.Value    ;
            _client.sexe           = sexecbx.SelectedIndex     ;
            _client.tel            = teltxt.Text               ;
            _client.idorganisme    = (int)organismecbx.SelectedValue;
            _client.coderecherche  = Utile.UglifyTextAr(_client.nom + _client.prenom);
        }
        
        void BindClient()
        {
            clientgrp.Enabled = false;
            nomtxt.Text = _client.nom;
            prenomtxt.Text = _client.prenom;
            if (_client.id <= 0)
                _client.datenaissance = DateTime.Now;
            TimeSpan ts = (DateTime.Now - _client.datenaissance);
            anneenum.Value = (int)(ts.Days/365.25);
            moisnum.Value = (int)(ts.Days / 30.25) - (12 * ((int)(ts.Days / 365.25)));
            journum.Value = (int)(ts.Days % 30.25);

            datenaissancedat.Value=  _client.datenaissance;
            sexecbx.SelectedIndex = _client.sexe;
            teltxt.Text =_client.tel;
            organismecbx.SelectedValue= _client.idorganisme;
        }

        private void InitLists()
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(LoadComboBoxSex));
            }
            else LoadComboBoxSex();

            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(LoadComboBoxOrganisme));
            }
            else LoadComboBoxOrganisme();

            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(LoadComboBoxMedecin));
            }
            else LoadComboBoxMedecin();

            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(LoadListeAnalyse));
            }
            else LoadListeAnalyse();

            MiseEnFormeAnalyseDestination();
        }

        private void LoadComboBoxMedecin()
        {
            docteurcbx.DataSource = new MedecinBLL().GetAll();
            docteurcbx.ValueMember = "id";
            docteurcbx.DisplayMember = "nom";
            docteurcbx.SelectedIndex = -1;
            docteurcbx.Validated += docteurcbx_Validated;
        }

        void docteurcbx_Validated(object sender, EventArgs e)
        {
            organismecbx.Focus();
        }

        private void MiseEnFormeAnalyseDestination()
        {
            RefreshAnalyseDestination();
            analysedestinationdgv.Rows.CollectionChanged += Rows_CollectionChanged;
            analysedestinationdgv.UserDeletingRow += analysedestinationdgv_UserDeletingRow;
            var dataGridViewColumn = analysedestinationdgv.Columns["id"];
            if (dataGridViewColumn != null) dataGridViewColumn.Visible = false;
            foreach (var column in analysedestinationdgv.Columns)
            {
                ((DataGridViewColumn) column).AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            }
            var gridViewColumn = analysedestinationdgv.Columns["designation"];
            if (gridViewColumn != null)
                gridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            analysedestinationdgv.ReadOnly = true;
            analysedestinationdgv.AllowUserToAddRows = false;
            #region rename columns
            var viewColumn = analysedestinationdgv.Columns["id"];
            if (viewColumn != null) viewColumn.Visible = false;
            var dataGridViewColumn1 = analysedestinationdgv.Columns["designation"];
            if (dataGridViewColumn1 != null)
                dataGridViewColumn1.HeaderText = Resources.analyse;
            var gridViewColumn1 = analysedestinationdgv.Columns["mnttotal"];
            if (gridViewColumn1 != null)
                gridViewColumn1.HeaderText = Resources.montant_total;
            var viewColumn1 = analysedestinationdgv.Columns["mntorganisme"];
            if (viewColumn1 != null)
                viewColumn1.HeaderText = Resources.contrat;
            var column1 = analysedestinationdgv.Columns["mntpatient"];
            if (column1 != null)
                column1.HeaderText = Resources.client;
            #endregion
        }

        void analysedestinationdgv_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            var dr = MessageBox.Show(Resources.confirm_supression, Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
            e.Cancel = true;
            //si l'action de supression est annule
            if (dr == DialogResult.Cancel)
            {
                e.Cancel = true;//annuler la supression de la ligne
                return;
            }
            if (analysedestinationdgv.CurrentRow != null)
            {
                int id = Convert.ToInt32(analysedestinationdgv.CurrentRow.Cells["id"].Value);
                _listDemandeAnalyse.Remove(
                    _listDemandeAnalyse.SingleOrDefault(x => x.id == id)
                    );
            }
            RefreshAnalyseDestination();
        }

        
        void Rows_CollectionChanged(object sender, CollectionChangeEventArgs e)
        {
            
            int i = 0;
            foreach (var d in _listDemandeAnalyse)
            {
                i++;
                _mnttotal += d.mnttotal;
                _mntpat += d.mntpatient;
            }
            mntpatientlbl.Text = String.Format("{0:C}", _mntpat);
            mnttotallbl.Text = String.Format("{0:C}", _mnttotal);
            countlbl.Text = i.ToString();
        }

        private void LoadListeAnalyse()
        {
            analysesourcedgv.AllowUserToDeleteRows = false;
            analysesourcedgv.AllowUserToAddRows = false;
            analysesourcedgv.ReadOnly = true;
            _bsListeAnalyse.DataSource = Utile.ListToDatatable(new AnalyseBLL().GetAll().ToList());
            analysesourcedgv.DataSource = _bsListeAnalyse;
            foreach (var col in analysesourcedgv.Columns)
            {
                ((DataGridViewColumn) col).Visible = false;
            }
            var dataGridViewColumn = analysesourcedgv.Columns["abriviation"];
            if (dataGridViewColumn != null)
            {
                dataGridViewColumn.Visible = true;
                dataGridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
            }
            var gridViewColumn = analysesourcedgv.Columns["designation"];
            if (gridViewColumn != null)
            {
                gridViewColumn.Visible = true;
                gridViewColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            }
            if(((DataTable) _bsListeAnalyse.DataSource).Rows.Count==0) return;
            filtreanalysetxt.TextChanged += filtreanalysetxt_TextChanged;
            analysesourcedgv.CellContentClick += analysesourcedgv_CellContentClick;
        }

        void analysesourcedgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (organismecbx.SelectedValue == null)
            {
                MessageBox.Show(Resources.veuillez_selectionner_le_contrat, Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                organismecbx.Focus();
                return;
            }
            if (analysesourcedgv.CurrentRow == null) return;
            int idAnalyse = Convert.ToInt32(analysesourcedgv.CurrentRow.Cells["id"].Value);
            var selectedAnalyse = _listPrixAnalyseOrganisme.SingleOrDefault(p => p.idanalyse == idAnalyse);
            if (selectedAnalyse == null)
            {
                MessageBox.Show(Resources.verifier_le_contrat, Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            var d = new DemandeAnalyse
            {
                designation = analysesourcedgv.CurrentRow.Cells["designation"].Value.ToString(),
                id = Convert.ToInt32(analysesourcedgv.CurrentRow.Cells["id"].Value),
                mnttotal = selectedAnalyse.prixtotal,
                mntorganisme = selectedAnalyse.partorganisme,
                mntpatient = selectedAnalyse.partpatient
            };
            if (_listDemandeAnalyse.All(x => x.id != d.id))
            {
                _listDemandeAnalyse.Add(d);
                RefreshAnalyseDestination();
                filtreanalysetxt.Text = String.Empty;
                filtreanalysetxt.Focus();
            }
            
        }

        private void RefreshAnalyseDestination()
        {
            _bsAnalyseDestination.DataSource = Utile.ListToDatatable(_listDemandeAnalyse); 
            analysedestinationdgv.DataSource = _bsAnalyseDestination;
            analysedestinationdgv.Refresh();
        }


        void filtreanalysetxt_TextChanged(object sender, EventArgs e)
        {
            _bsListeAnalyse.Filter = String.Format("abriviation like '%{0}%' or designation like '%{0}%'", ((TextBox) sender).Text);
        }

        private void LoadComboBoxOrganisme()
        {
            organismecbx.DataSource = new OrganismeBLL().GetAll();
            organismecbx.ValueMember = "id";
            organismecbx.DisplayMember = "designation";
            organismecbx.SelectedIndex = -1;
            organismecbx.Validated += organismecbx_Validated;
        }

        void organismecbx_Validated(object sender, EventArgs e)
        {
            if(((ComboBox)sender).SelectedValue==null)return;
            _listPrixAnalyseOrganisme = new PrixAnalyseOrganismeBLL().GetByIdOrganisme((int)(((ComboBox)sender).SelectedValue)).ToList();
            _listDemandeAnalyse = new List<DemandeAnalyse>();
            RefreshAnalyseDestination();
            filtreanalysetxt.Focus();
        }

        private void LoadComboBoxSex()
        {
            sexecbx.DataSource = Enum.GetValues(typeof (Model.Enums.EnumerationsAr.Sexe));
            sexecbx.SelectedIndex = -1;
        }


        void AjoutDemande_Activated(object sender, EventArgs e)
        {
            Thread thread = new Thread(ResizeColumnsForBigData);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        #region grid client
        private void ResizeColumnsForBigData()
        {
            if (InvokeRequired)
                Invoke(new MethodInvoker(ResizeColumnsForBigData));
            else
            {
                Thread.Sleep(3000);
                var dataGridViewColumn = clientsdgv.Columns["datenaissance"];
                if (dataGridViewColumn != null) dataGridViewColumn.Width = 80;
                var gridViewColumn = clientsdgv.Columns["nomComplet"];
                if (gridViewColumn != null) gridViewColumn.Width = 209;
            }
        }

        void AjoutDemande_Load(object sender, EventArgs e)
        {
            clientsdgv.Refresh();
            Application.DoEvents();
            while (StaticVar.BsClients.DataSource == null)
            {
                Thread.Sleep(100);
            }
            Thread.Sleep(100);
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(delegate { clientsdgv.DataSource = StaticVar.BsClients; }));
            }
            else
            {
                Application.DoEvents();
                clientsdgv.DataSource = StaticVar.BsClients;
            }
            
            //clientsdgv.Refresh();
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(MiseEnFormeGrid));
            }
            else MiseEnFormeGrid();

            
            Closing += AjoutDemande_Closing;
        }

        void MiseEnFormeGrid()
        {
            // ReSharper disable PossibleNullReferenceException
            clientsdgv.Columns["id"].Visible =
                clientsdgv.Columns["nom"].Visible =
                clientsdgv.Columns["prenom"].Visible =
                clientsdgv.Columns["tel"].Visible =
                clientsdgv.Columns["sexe"].Visible =
                clientsdgv.Columns["ageday"].Visible =
                clientsdgv.Columns["idorganisme"].Visible =
                clientsdgv.Columns["coderecherche"].Visible = false; //cacher la column id et Resultats
            clientsdgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            clientsdgv.ReadOnly = true;
        }
        #endregion

        void AjoutDemande_Closing(object sender, CancelEventArgs e)
        {
            StaticVar.BsClients.Filter = String.Empty;
            Utile.LoadAllClient();
        }

        private void nomtxt_TextChanged(object sender, EventArgs e)
        {
            if (_client.id > 0) return;
            var n = string.Empty;
            var p=string.Empty;
            var s = string.Empty;
            if (!string.IsNullOrEmpty(nomtxt.Text.Trim()))
                n = String.Format("or nom like '%{0}%'",nomtxt.Text);
            if (!string.IsNullOrEmpty(prenomtxt.Text.Trim()))
                p = String.Format("and prenom like '%{0}%'", prenomtxt.Text);

            if (sexecbx.SelectedIndex != -1)
                s = String.Format("and sexe = {0}", sexecbx.SelectedIndex);
            string filter = string.Format("(coderecherche like '%{0}%' {1} {2}) {3}",
                Utile.UglifyTextAr(nomtxt.Text + prenomtxt.Text), n, p,s);
            StaticVar.BsClients.Filter = filter;
        }

        private void datenaissancedat_Validated(object sender, EventArgs e)
        {
            
            _client.datenaissance = (sender as DateTimePicker).Value;

            if (_client.datenaissance > DateTime.Now) return;
            if (_client.datenaissance >= DateTime.MaxValue) return;
            if (_client.datenaissance <= DateTime.MinValue) return;
            //ToDo: corriger bocle infini
            TimeSpan ts = (DateTime.Now - _client.datenaissance);
            anneenum.ValueChanged -= CalculerDateDeNaissance;
            moisnum.ValueChanged -= CalculerDateDeNaissance;
            journum.ValueChanged -= CalculerDateDeNaissance;
            anneenum.Value = (int)(ts.Days / 365.25);
            moisnum.Value = (int)(ts.Days / 30.25) - (12 * ((int)(ts.Days / 365.25)));
            journum.Value = (int)(ts.Days % 30.25);
            anneenum.ValueChanged += CalculerDateDeNaissance;
            moisnum.ValueChanged += CalculerDateDeNaissance;
            journum.ValueChanged += CalculerDateDeNaissance;

        }

        private void CalculerDateDeNaissance(object sender, EventArgs e)
        {
            var val =(int) (sender as NumericUpDown).Value;
            var dateNow = DateTime.Now;
            datenaissancedat.Validated -= datenaissancedat_Validated;
            switch ((sender as NumericUpDown).Tag.ToString())
            {
                case "d":
                    datenaissancedat.Value = new DateTime(datenaissancedat.Value.Year, datenaissancedat.Value.Month, dateNow.Day, 0, 0, 0);
                    datenaissancedat.Value = datenaissancedat.Value.AddDays(-1*val);
                    break;
                case "m":
                    datenaissancedat.Value = new DateTime(datenaissancedat.Value.Year, dateNow.Month, datenaissancedat.Value.Day, 0, 0, 0);
                    datenaissancedat.Value = datenaissancedat.Value.AddMonths(-1 * val);
                    break;
                case "y":
                    datenaissancedat.Value = new DateTime(dateNow.Year, datenaissancedat.Value.Month, datenaissancedat.Value.Day, 0, 0, 0);
                    datenaissancedat.Value = datenaissancedat.Value.AddYears(-1 * val);
                    break;
            }
            datenaissancedat.Validated += datenaissancedat_Validated;
        }

        private void okbtn_Click(object sender, EventArgs e)
        {
            //ToDo: veifier les informations saisie
            if (string.IsNullOrEmpty(nomtxt.Text)) return;
            if (string.IsNullOrEmpty(prenomtxt.Text))return;
            if (datenaissancedat.Value>DateTime.Now) return;
            if (datenaissancedat.Value >= DateTime.MaxValue) return;
            if (datenaissancedat.Value <= DateTime.MinValue) return;

            if (sexecbx.SelectedIndex == -1) return;
            if (organismecbx.SelectedValue == null) return;
            if (!_listDemandeAnalyse.Any()) return;

            if (_client.id <= 0)
            {
                GetClient();
                _client = _clientBll.Add(_client);
            }
            else _clientBll.Update(_client);
            var demande = _demandeBll.Add(new Demande
            {
                idclient = _client.id,
                datedemande = DateTime.Now,
                dateordenance = dateordenancedat.Value,
                dateprelevement = dateprelevementdat.Value,
                idmedecin = (int) docteurcbx.SelectedValue,
                infomedicale = renseignementtxt.Text,
                iduser = ((Utilisateur) StaticVar.CurrentUser).id,
                montanttotal = _mnttotal,
                montantclient = _mntpat,
                montantorganisme = _mnttotal - _mntpat,
                resultatvalide = 0
            });
            foreach (var demandeAnalysis in _listDemandeAnalyse)
            {
                _detailDemandeBll.Add(new DetailDemande
                {
                    idanalyse = demandeAnalysis.id,
                    iddemande = demande.id
                });
            }
            //ToDo: print recu client
            Close();
        }

        private void initClientbtn_Click(object sender, EventArgs e)
        {
            _client = new Client();
            clientgrp.Enabled = true;
        }

        private void addMedecinbtn_Click(object sender, EventArgs e)
        {
            new UI.Parametrage.Medecin().ShowDialog();
            LoadComboBoxMedecin();
        }

        private void addOrganismebtn_Click(object sender, EventArgs e)
        {
            new UI.Parametrage.Organisme().ShowDialog();
            LoadComboBoxOrganisme();
        }
    }
}
